{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 严格模式\n",
    "\n",
    "**严格模式**（strict mode）是ECMAScript 5 引入的概念。严格模式为JavaScript定义了一种不同的解析与执行模型，在严格模式下，一些早起版本中的不确定行为得到了处理，从而使代码显示地 脱离“马虎模式/稀松模式/懒散模式“（sloppy）模式。\n",
    "\n",
    "严格模式对正常的 JavaScript语义做了一些更改。\n",
    "\n",
    "* 严格模式通过抛出错误来消除了一些原有静默错误。\n",
    "* 严格模式修复了一些导致 JavaScript引擎难以执行优化的缺陷：有时候，相同的代码，严格模式可以比非严格模式下运行得更快。\n",
    "* 严格模式禁用了在ECMAScript的未来版本中可能会定义的一些语法。\n",
    "\n",
    "要在整个脚本中启用严格模式，可以在顶部添加如下代码："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'use strict'"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\"use strict\";"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "也可以下局部使用，如脚本内部，或者函数内部使用。\n",
    "\n",
    "```html\n",
    "<script>\n",
    "    'use strict';\n",
    "</script>\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "undefined"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "function test() {\n",
    "    'use strict';\n",
    "    // do something     \n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "建议按一个个函数去开启严格模式，也可以将整个脚本的内容用一个函数包括起来，然后在这个外部函数中使用严格模式。这样做就可以消除合并的问题，但是这就意味着您必须要在函数作用域外声明一个全局变量。\n",
    "\n",
    "记得在支持或者不支持严格模式的浏览器中测试你的代码。如果你只在不支持严格模式的浏览器中测试，那么在支持的浏览器中就很有可能出问题，反之亦然。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 严格模式与正常模式的区别\n",
    "\n",
    "1. 不能为未经声明的变量赋值。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2020\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "undefined"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "function test() {\n",
    "    return year = 2020;\n",
    "}\n",
    "console.log(test())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "ename": "ReferenceError",
     "evalue": "year2 is not defined",
     "output_type": "error",
     "traceback": [
      "evalmachine.<anonymous>:3",
      "    return year2 = 2020;",
      "                 ^",
      "",
      "ReferenceError: year2 is not defined",
      "    at test (evalmachine.<anonymous>:3:18)",
      "    at evalmachine.<anonymous>:6:13",
      "    at Script.runInThisContext (vm.js:120:20)",
      "    at Object.runInThisContext (vm.js:311:38)",
      "    at run ([eval]:1054:15)",
      "    at onRunRequest ([eval]:888:18)",
      "    at onMessage ([eval]:848:13)",
      "    at process.emit (events.js:311:20)",
      "    at emit (internal/child_process.js:876:12)",
      "    at processTicksAndRejections (internal/process/task_queues.js:85:21)"
     ]
    }
   ],
   "source": [
    "function test() {\n",
    "    'use strict';\n",
    "    return year2 = 2020;\n",
    "    \n",
    "}\n",
    "console.log(test())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "不能定义名为`eval`或`arguments`的变量。\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "undefined"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "function test() {\n",
    "    var eval = 2;\n",
    "    console.log(eval);\n",
    "}\n",
    "\n",
    "test();"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "Unexpected eval or arguments in strict mode",
     "output_type": "error",
     "traceback": [
      "evalmachine.<anonymous>:3",
      "    var eval = 2;",
      "        ^^^^",
      "",
      "SyntaxError: Unexpected eval or arguments in strict mode",
      "    at new Script (vm.js:88:7)",
      "    at createScript (vm.js:263:10)",
      "    at Object.runInThisContext (vm.js:311:10)",
      "    at run ([eval]:1054:15)",
      "    at onRunRequest ([eval]:888:18)",
      "    at onMessage ([eval]:848:13)",
      "    at process.emit (events.js:311:20)",
      "    at emit (internal/child_process.js:876:12)",
      "    at processTicksAndRejections (internal/process/task_queues.js:85:21)"
     ]
    }
   ],
   "source": [
    "function test() {\n",
    "    'use strict';\n",
    "    var eval = 2;\n",
    "    console.log(eval);\n",
    "}\n",
    "\n",
    "test();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 参考资料\n",
    "\n",
    "<https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Strict_mode>\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Javascript (Node.js)",
   "language": "javascript",
   "name": "javascript"
  },
  "language_info": {
   "file_extension": ".js",
   "mimetype": "application/javascript",
   "name": "javascript",
   "version": "12.16.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
